/*
 * Fichier: ListeDeJeux.java
 * Crée le: 21 mars 2012.
 * Modifié: 21 mars 2012.
 * Auteurs: Sébastien ESTIENNE.
 * SiteWeb: http://www.prog-info.org/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package chapitre13;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

/**
 * <p>Classe représentant une liste (de jeux de société en l'occurence) qu'il est possible de gérer 
 * (Ajout, Modification et suppression). Un historique des actions effectuées est aussi 
 * disponible.</p>
 * TODO : Séparer en 5 méthodes ? Préfixer de this ?
 * @author Sébastien ESTIENNE.
 */
public class ListeDeJeux extends JFrame {

    /** <p>Serial version UID.</p> */
    private static final long serialVersionUID = 1L;
    
    /** Modèle représentant les éléments de la liste graphique. */
    private DefaultListModel modele = null;
    
    /** Représentation graphique de la liste. */
    private JList liste = null;
    
    /** Zone de texte pour l'historique des actions effectuées. */
    private JTextArea historique = null;
    
    /**
     * Constructeur s'occupant d'initialiser la fenêtre.
     */
    public ListeDeJeux() {
        super("Liste de jeux de société");

        // Conteneur.
        Container conteneur = getContentPane();
        
        
        // Initialise le modèle.
        this.modele = new DefaultListModel();
        this.modele.addElement("Jungle speed");
        this.modele.addElement("Time's up");
        
        // Initialise la liste à partir du modèle et l'attache à une barre de défilement.
        this.liste = new JList(this.modele);
        JScrollPane defilement = new JScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        defilement.setViewportView(this.liste);
        
        // Ajoute la liste à la fenêtre.
        conteneur.add(defilement, BorderLayout.WEST);
        
        
        // Crée la zone de texte de l'historique.
        this.historique = new JTextArea();
        this.historique.setEditable(false);
        
        // Crée une étiquette "Historique".
        JLabel etiquetteHistorique = new JLabel("Historique :");
        
        // Initialise un panneau avec la zone de texte et l'étiquette.
        JPanel panneauHistorique = new JPanel();
        panneauHistorique.setLayout(new BorderLayout());
        panneauHistorique.add(etiquetteHistorique, BorderLayout.NORTH);
        panneauHistorique.add(new JScrollPane(historique), BorderLayout.CENTER);
        
        // Ajoute le panneau contenant les éléments graphiques de l'historique.
        conteneur.add(panneauHistorique, BorderLayout.CENTER);
        
        
        // Initialise l'élément de menu "Ajouter" pour ajouter un nouveau jeu à la liste.
        JMenuItem elementAjouter = new JMenuItem("Ajouter");
        elementAjouter.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // Demande le nom du jeu.
                String jeu = JOptionPane.showInputDialog(ListeDeJeux.this, 
                        "Saisissez le nom du jeu à ajouter :", "Ajouter un jeu", 
                        JOptionPane.QUESTION_MESSAGE);
                
                if(jeu != null) {
                    // Ajoute le nom du jeu.
                    ListeDeJeux.this.modele.addElement(jeu);
                
                    // Historise l'action.
                    ListeDeJeux.this.historique.insert("Ajout du jeu \"" + jeu + "\".\n", 
                            ListeDeJeux.this.historique.getText().length());
                }
            }
        });
        
        // Initialise l'élément de menu "Modifier" pour renommer un jeu sélectionné de la liste.
        JMenuItem elementModifier = new JMenuItem("Modifier");
        elementModifier.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // Récupère l'élément sélectionné.
                int index = ListeDeJeux.this.liste.getSelectedIndex();
                
                // Un élément est sélectionné dans la liste.
                if(index >= 0) {
                    // Demande le nom du nouveau jeu.
                    String nouveauJeu = (String) JOptionPane.showInputDialog(ListeDeJeux.this, 
                            "Saisissez le nouveau nom du jeu :", "Modifier un jeu", 
                            JOptionPane.QUESTION_MESSAGE, null, null, 
                            ListeDeJeux.this.modele.get(index));
                    
                    if(nouveauJeu != null) {
                        // Renomme en supprimant l'ancien jeu et en ajoutant le nouveau.
                        // (Un objet de type String est immuable.)
                        String ancienJeu = (String) ListeDeJeux.this.modele.remove(index);
                        ListeDeJeux.this.modele.add(index, nouveauJeu);
                    
                        // Historise l'action.
                        ListeDeJeux.this.historique.insert("Renommage du jeu \"" + ancienJeu 
                                + "\" en \"" + nouveauJeu + "\".\n", historique.getText().length());
                    }
                }
                // Aucun élément sélectionné dans la liste.
                else {
                    JOptionPane.showMessageDialog(ListeDeJeux.this, "Aucun jeu n'est sélectionné!", 
                            "Erreur de modification", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        
        // Initialise l'élément de menu "Supprimer" pour supprimer le jeu sélectionné de la liste.
        JMenuItem elementSupprimer = new JMenuItem("Supprimer");
        elementSupprimer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // Récupère l'élément sélectionné.
                int index = ListeDeJeux.this.liste.getSelectedIndex();
                
                // Un élément est sélectionné dans la liste.
                if(index >= 0) {
                    // Supprime le jeu sélectionné.
                    String jeu = (String) ListeDeJeux.this.modele.remove(index);
                    
                    // Historise l'action.
                    ListeDeJeux.this.historique.insert("Suppression du jeu \"" + jeu + "\".\n", 
                            ListeDeJeux.this.historique.getText().length());
                }
                // Aucun élément sélectionné dans la liste.
                else {
                    JOptionPane.showMessageDialog(ListeDeJeux.this, "Aucun jeu n'est sélectionné!", 
                            "Erreur de suppression", JOptionPane.ERROR_MESSAGE);
                }
            }
        });
        
        // Crée le menu contextuel de la liste.
        JPopupMenu popup = new JPopupMenu();
        popup.add(elementAjouter);
        popup.add(elementModifier);
        popup.add(elementSupprimer);
        
        // Ajoute l'écouteur permettant d'afficher le menu contextuel de la liste.
        MouseListener popupListener = new PopupListener(popup);
        this.liste.addMouseListener(popupListener);
        
        
        // Initialise l'élément de menu permettant de vider l'historique.
        JMenuItem elementVider = new JMenuItem("Vider");
        elementVider.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // Vide la zone d'historique.
                ListeDeJeux.this.historique.setText("");
            }
        });
        
        // Crée le menu contextuel de l'historique.
        JPopupMenu popupHistorique = new JPopupMenu();
        popupHistorique.add(elementVider);
        
        // Ajoute l'écouteur permettant d'afficher le menu contextuel de l'historique.
        MouseListener popupListener2 = new PopupListener(popupHistorique);
        ListeDeJeux.this.historique.addMouseListener(popupListener2);
        
        // Propriétés de la fenêtre.
        setLocation(50, 50);
        setSize(350, 200);
        setVisible(true);
        setResizable(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    /**
     * Ecouteur de menu contextuel.
     */
    private class PopupListener extends MouseAdapter {
        /** Le menu contextuel. */
        private JPopupMenu popupMenu;
 
        /**
         * Constructeur initialisant le menu contextuel.
         * @param popupMenu Le menu contextuel.
         */
        PopupListener(JPopupMenu popupMenu) {
            this.popupMenu = popupMenu;
        }
 
        /**
         * Lorsque le bouton de la souris est pressé, calcule s'il faut afficher le menu contextuel.
         * @param event L'événement de souris.
         */
        public void mousePressed(MouseEvent event) {
            maybeShowPopup(event);
        }
 
        /**
         * Lorsque le bouton de la souris est relaché, calcule s'il faut afficher le menu 
         * contextuel.
         * @param event L'événement de souris.
         */
        public void mouseReleased(MouseEvent event) {
            maybeShowPopup(event);
        }
 
        /**
         * Affiche le menu contextuel.
         * @param event L'événement de souris.
         */
        private void maybeShowPopup(MouseEvent event) {
            if (event.isPopupTrigger()) {
                popupMenu.show(event.getComponent(), event.getX(), event.getY());
            }
        }
    }
    
    /**
     * <p>Débute l'exécution du programme.</p>
     * @param args Les paramètres de la ligne de commande.
     */
    public static void main(String[] args)
    {
        new ListeDeJeux();
    }
}
